home *** CD-ROM | disk | FTP | other *** search
- package PPI::Dumper;
-
- =pod
-
- =head1 NAME
-
- PPI::Dumper - Dumping of PDOM trees
-
- =head1 SYNOPSIS
-
- # Load a document
- my $Module = PPI::Document->new( 'MyModule.pm' );
-
- # Create the dumper
- my $Dumper = PPI::Dumper->new( $Module );
-
- # Dump the document
- $Dumper->print;
-
- =head1 DESCRIPTION
-
- The PDOM trees in PPI are quite complex, and getting a dump of their
- structure for development and debugging purposes is important.
-
- This module provides that functionality.
-
- The process is relatively simple. Create a dumper object with a
- particular set of options, and then call one of the dump methods to
- generate the dump content itself.
-
- =head1 METHODS
-
- =cut
-
- use strict;
- use Params::Util qw{_INSTANCE};
-
- use vars qw{$VERSION};
- BEGIN {
- $VERSION = '1.213';
- }
-
-
-
-
-
- #####################################################################
- # Constructor
-
- =pod
-
- =head2 new $Element, param => value, ...
-
- The C<new> constructor creates a dumper, and takes as argument a single
- L<PPI::Element> object of any type to serve as the root of the tree to
- be dumped, and a number of key-E<gt>value parameters to control the output
- format of the Dumper. Details of the parameters are listed below.
-
- Returns a new C<PPI::Dumper> object, or C<undef> if the constructor
- is not passed a correct L<PPI::Element> root object.
-
- =over
-
- =item memaddr
-
- Should the dumper print the memory addresses of each PDOM element.
- True/false value, off by default.
-
- =item indent
-
- Should the structures being dumped be indented. This value is numeric,
- with the number representing the number of spaces to use when indenting
- the dumper output. Set to '2' by default.
-
- =item class
-
- Should the dumper print the full class for each element.
- True/false value, on by default.
-
- =item content
-
- Should the dumper show the content of each element. True/false value,
- on by default.
-
- =item whitespace
-
- Should the dumper show whitespace tokens. By not showing the copious
- numbers of whitespace tokens the structure of the code can often be
- made much clearer. True/false value, on by default.
-
- =item comments
-
- Should the dumper show comment tokens. In situations where you have
- a lot of comments, the code can often be made clearer by ignoring
- comment tokens. True/value value, on by default.
-
- =item locations
-
- Should the dumper show the location of each token. The values shown are
- [ line, rowchar, column ]. See L<PPI::Element/"location"> for a description of
- what these values really are. True/false value, off by default.
-
- =back
-
- =cut
-
- sub new {
- my $class = shift;
- my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
-
- # Create the object
- my $self = bless {
- root => $Element,
- display => {
- memaddr => '', # Show the refaddr of the item
- indent => 2, # Indent the structures
- class => 1, # Show the object class
- content => 1, # Show the object contents
- whitespace => 1, # Show whitespace tokens
- comments => 1, # Show comment tokens
- locations => 0, # Show token locations
- },
- }, $class;
-
- # Handle the options
- my %options = map { lc $_ } @_;
- foreach ( keys %{$self->{display}} ) {
- if ( exists $options{$_} ) {
- if ( $_ eq 'indent' ) {
- $self->{display}->{indent} = $options{$_};
- } else {
- $self->{display}->{$_} = !! $options{$_};
- }
- }
- }
-
- $self->{indent_string} = join '', (' ' x $self->{display}->{indent});
-
- $self;
- }
-
-
-
-
-
- #####################################################################
- # Main Interface Methods
-
- =pod
-
- =head2 print
-
- The C<print> method generates the dump and prints it to STDOUT.
-
- Returns as for the internal print function.
-
- =cut
-
- sub print {
- CORE::print(shift->string);
- }
-
- =pod
-
- =head2 string
-
- The C<string> method generates the dump and provides it as a
- single string.
-
- Returns a string or undef if there is an error while generating the dump.
-
- =cut
-
- sub string {
- my $array_ref = shift->_dump or return undef;
- join '', map { "$_\n" } @$array_ref;
- }
-
- =pod
-
- =head2 list
-
- The C<list> method generates the dump and provides it as a raw
- list, without trailing newlines.
-
- Returns a list or the null list if there is an error while generation
- the dump.
-
- =cut
-
- sub list {
- my $array_ref = shift->_dump or return ();
- @$array_ref;
- }
-
-
-
-
-
- #####################################################################
- # Generation Support Methods
-
- sub _dump {
- my $self = ref $_[0] ? shift : shift->new(shift);
- my $Element = _INSTANCE($_[0], 'PPI::Element') ? shift : $self->{root};
- my $indent = shift || '';
- my $output = shift || [];
-
- # Print the element if needed
- my $show = 1;
- if ( $Element->isa('PPI::Token::Whitespace') ) {
- $show = 0 unless $self->{display}->{whitespace};
- } elsif ( $Element->isa('PPI::Token::Comment') ) {
- $show = 0 unless $self->{display}->{comments};
- }
- push @$output, $self->_element_string( $Element, $indent ) if $show;
-
- # Recurse into our children
- if ( $Element->isa('PPI::Node') ) {
- my $child_indent = $indent . $self->{indent_string};
- foreach my $child ( @{$Element->{children}} ) {
- $self->_dump( $child, $child_indent, $output );
- }
- }
-
- $output;
- }
-
- sub _element_string {
- my $self = ref $_[0] ? shift : shift->new(shift);
- my $Element = _INSTANCE($_[0], 'PPI::Element') ? shift : $self->{root};
- my $indent = shift || '';
- my $string = '';
-
- # Add the memory location
- if ( $self->{display}->{memaddr} ) {
- $string .= $Element->refaddr . ' ';
- }
-
- # Add the location if such exists
- if ( $self->{display}->{locations} ) {
- my $loc_string;
- if ( $Element->isa('PPI::Token') ) {
- my $location = $Element->location;
- if ($location) {
- $loc_string = sprintf("[ % 4d, % 3d, % 3d ] ", @$location);
- }
- }
- # Output location or pad with 20 spaces
- $string .= $loc_string || " " x 20;
- }
-
- # Add the indent
- if ( $self->{display}->{indent} ) {
- $string .= $indent;
- }
-
- # Add the class name
- if ( $self->{display}->{class} ) {
- $string .= ref $Element;
- }
-
- if ( $Element->isa('PPI::Token') ) {
- # Add the content
- if ( $self->{display}->{content} ) {
- my $content = $Element->content;
- $content =~ s/\n/\\n/g;
- $content =~ s/\t/\\t/g;
- $string .= " \t'$content'";
- }
-
- } elsif ( $Element->isa('PPI::Structure') ) {
- # Add the content
- if ( $self->{display}->{content} ) {
- my $start = $Element->start
- ? $Element->start->content
- : '???';
- my $finish = $Element->finish
- ? $Element->finish->content
- : '???';
- $string .= " \t$start ... $finish";
- }
- }
-
- $string;
- }
-
- 1;
-
- =pod
-
- =head1 SUPPORT
-
- See the L<support section|PPI/SUPPORT> in the main module.
-
- =head1 AUTHOR
-
- Adam Kennedy E<lt>adamk@cpan.orgE<gt>
-
- =head1 COPYRIGHT
-
- Copyright 2001 - 2010 Adam Kennedy.
-
- This program is free software; you can redistribute
- it and/or modify it under the same terms as Perl itself.
-
- The full text of the license can be found in the
- LICENSE file included with this module.
-
- =cut
-